#ifndef _PBVP_ENVIRONMENT_H
#define _PBVP_ENVIRONMENT_H

#include <QString>
#include <QList>

#include "light.h"
#include "material.h"
#include "../math/Matrix4.h"

namespace PBVP {
	typedef enum {
		CULL_BACK = 0,
		CULL_FRONT = 1,
		NO_CULL = 2
	} CullMode;

	/// Global OpenGL Rendering Environment
	/** 
	 * If one render changes the environment, it would affect others.
	 */
	class Environment {
	public:
		Environment();

		/** 
		* Construct with a single light l 
		*/
		Environment(const Light& l, const Material& m);

		/// Copy Constructor
		Environment(const Environment& env);
		/// Construct based on a given config file
		Environment(const QString& fname);
		/// Destructor
		~Environment(){}

		/// Assignment operator
		Environment& operator = (const Environment& env);

		/// <summary>
		/// configure the viewing enviorment using a file
		/// </summary>
		/// <param name="fname"></param>
		/// <returns>bool</returns>
		bool readConfig(const QString& fname);

		/**
		 *	Apply changes to the OpenGL state machine
		 */
		void apply();

		/// Number of lights
		unsigned int numOfLights() const {return m_NumOfLights;}

		/// Accessors
		Light& light(unsigned int n = 0);
		const Light& light(unsigned int n = 0) const;

		Material& material() {
			return m_Material;
		}
		const Material& material() const {
			return m_Material;
		}
		Color& backgroundColor() {
			return m_BackgroundColor;
		}
		const Color& backgorundColor() const {
			return m_BackgroundColor;
		}
		Color& defaultColor() {
			return m_DefaultColor;
		}
		const Color& defaultColor() const {
			return m_DefaultColor;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="l"></param>
		/// <returns>bool</returns>
		bool addLight(const Light& l);
		/// <summary>
		/// 
		/// </summary>
		/// <param name="n"></param>
		void removeLight(unsigned int n);

		void setMaterial(const Material& m) {
			m_Material = m;
		}

		void setBackgroundColor(const Color& c) {
			m_BackgroundColor = c;
		}

		void setDefColor(const Color& c) {
			m_DefaultColor = c;
		}

		CullMode& cullmode() {
			return m_CullMode;
		}
		const CullMode& cullmode() const {
			return m_CullMode;
		}

		void setCullMode(const CullMode& mode) {
			m_CullMode = mode;
		}

		static const unsigned int    MAX_LIGHT_COUNT;

		Matrix4 getViewingTransform() const {
			return m_ViewTransform;
		}

		void setViewingTransform(const Matrix4& mtx4) {
			m_ViewTransform = mtx4;
		}

	private: 
		/// Set default values for the display environment
		void setDefaults();

		// number of lights
		unsigned int        m_NumOfLights;					
		QList<Light>		m_LightList;
		// default material in case object material not set
		Material            m_Material;
		// default color if object color not set
		Color				m_DefaultColor;
		// Background color of the window
		Color				m_BackgroundColor;
		// Culling mode
		CullMode			m_CullMode;

		// global viewing transformations
		Matrix4 m_ViewTransform;
	};
}
#endif

